package com.szwistar.common.comm.jsonrpc.udp;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.ArrayList;
import java.util.List;

import org.apache.mina.core.buffer.IoBuffer;

import com.szwistar.common.comm.blocktrans.BlockTransPayload;
import com.szwistar.common.datastruct.JsonMapper;

/**
 * JSON-RPC 返回值
 */
public class JsonRpcResult implements BlockTransPayload {
	// 帧类型 ID
	public static final short TYPEID = 0x1010;

	// 常用错误码常量
	public static final int PENDING = (-1);
	public static final int OK = (0);
	public static final int CANCEL = (1);

	public static final int NO_SERVICE = (404);
	public static final int NO_OBJECT = (405);
	public static final int NO_METHOD = (406);
	public static final int BAD_PARAM = (407);
	public static final int EXCEPTION = (500);


	// 默认的 JSON 字符编解码器
	protected CharsetDecoder charsetDecoder = Charset.forName("UTF-8").newDecoder();
	protected CharsetEncoder charsetEncoder = Charset.forName("UTF-8").newEncoder();

	// 会话token(8字节)
	protected long token;
	// 命令序列号(2字节)
	protected short sn;

	// 错误码
	protected int code;

	// 返回值
	protected Object returnValue;

	public JsonRpcResult() {
	}

	/**
	 * 构造函数(从缓冲区中解码出来)
	 * @param in
	 * @throws Exception
	 */
	public JsonRpcResult(IoBuffer in, int length) throws Exception {
		decode(in, length);
	}

	public JsonRpcResult(JsonRpcRequest req, int code) {
		this.token = req.token;
		this.sn = req.sn;
		this.code = code;
	}

	public JsonRpcResult(JsonRpcRequest req, Object returnValue) {
		this(req, 0);
		this.returnValue = returnValue;
	}

	public JsonRpcResult(JsonRpcRequest req, int code, String errorMessage) {
		this(req, code);
		this.returnValue = errorMessage;
	}

	@Override
	public short typeId() { return TYPEID; }

	public long getToken() {
		return token;
	}

	public void setToken(long token) {
		this.token = token;
	}

	public short getSn() {
		return sn;
	}

	public void setSn(short sn) {
		this.sn = sn;
	}

	/**
	 * 解码帧数据
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void decode(IoBuffer in, int length) throws Exception {
		token = in.getLong();
		sn = in.getShort();

		String json = in.getString(length-10, charsetDecoder);
		List<Object> list = JsonMapper.fromJson(json, ArrayList.class);

		code = (int) list.get(0);
		returnValue = list.get(1);
	}

	/**
	 * 把帧编码并放入缓冲区
	 * @param out
	 * @throws Exception
	 */
	@Override
	public void encode(IoBuffer out) throws Exception {
		out.putLong(token);
		out.putShort(sn);

		List<Object> body = new ArrayList<Object>();
		body.add(code);
		body.add(returnValue);
		String json = JsonMapper.toJson(body);
		out.putString(json, charsetEncoder);
	}

	@Override
	public String toString() {
		try {
			return String.format("%s(token=%016X, sn=0x%04X, code=0x%04X, ret='%s')",
					this.getClass().getSimpleName(),
					token, sn, code, JsonMapper.toJson(returnValue));
		} catch (Exception e) {
			return super.toString();
		}
	}
}
